package io.task.cc.network.spi.server;

import io.task.cc.network.ReadCompletionHandler;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;


/**
 * @author huihui
 */
@Slf4j
@Setter
@Getter
public class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Server> {


    public AcceptCompletionHandler() {
    }


    @Override
    public void completed(AsynchronousSocketChannel asynchronousSocketChannel, Server server) {
        try {
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 64 * 1024);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_SNDBUF, 64 * 1024);
            asynchronousSocketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
            //
            ServerConfig serverConfig = server.getServerConfig();
            ServerChannelContext serverChannelContext = new ServerChannelContext(serverConfig, asynchronousSocketChannel);
            serverChannelContext.setClosed(false);
            serverChannelContext.channelStat.setTimeFirstConnected(System.currentTimeMillis());
            serverChannelContext.setServerNode(server.getServerNode());

            serverConfig.ips.bind(serverChannelContext);


            if (!server.isWaitingStop()) {
                ReadCompletionHandler readCompletionHandler = serverChannelContext.getReadCompletionHandler();
                ByteBuffer readByteBuffer = readCompletionHandler.getReadByteBuffer();//ByteBuffer.allocateDirect(channelContext.tioConfig.getReadBufferSize());
                readByteBuffer.position(0);
                readByteBuffer.limit(readByteBuffer.capacity());
                asynchronousSocketChannel.read(readByteBuffer, readByteBuffer, readCompletionHandler);
            }
        } catch (Throwable e) {
            log.error("", e);
        } finally {
            if (server.isWaitingStop()) {
                log.info("{}即将关闭服务器，不再接受新请求", server.getServerNode());
            } else {
                AsynchronousServerSocketChannel serverSocketChannel = server.getAsynchronousServerSocketChannel();
                serverSocketChannel.accept(server, this);
            }
        }
    }


    @Override
    public void failed(Throwable throwable, Server server) {
        AsynchronousServerSocketChannel asynchronousServerSocketChannel = server.getAsynchronousServerSocketChannel();
        asynchronousServerSocketChannel.accept(server, this);
        log.error("[" + server.getServerNode() + "]监听出现异常", throwable);

    }

}
